﻿namespace XGameLibrary.TileEngine
{
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;

    using XGameLibrary.Input;
    using XGameLibrary.SpriteClasses;

    public enum CameraMode { Free, Follow }

    public class Camera
    {
        private Vector2 position;
        private float speed;
        private CameraMode mode;

        public Camera(Rectangle viewportRect)
        {
            this.Speed = 4f;
            this.Zoom = 1f;
            this.ViewportRectangle = viewportRect;
            this.mode = CameraMode.Follow;
        }

        public Camera(Rectangle viewportRect, Vector2 position) :
            this(viewportRect)
        {
            this.position = position;
        }

        public Vector2 Position
        {
            get { return this.position; }
            set { this.position = position; }
        }

        public float Speed
        {
            get
            {
                return this.speed;
            }

            set
            {
                this.speed = MathHelper.Clamp(value, 1f, 16f);
            }
        }

        public float Zoom { get; private set; }

        public CameraMode CameraMode
        {
            get
            {
                return this.mode;
            }
        }

        private Rectangle ViewportRectangle { get; set; }

        public void Update(GameTime gameTime)
        {
            if (this.mode == CameraMode.Follow)
            {
                return;
            }

            Vector2 motion = Vector2.Zero;

            if (InputHandler.KeyDown(Keys.Left))
            {
                motion.X = -this.Speed;
            }
            else if (InputHandler.KeyDown(Keys.Right))
            {
                motion.X = this.Speed;
            }

            if (InputHandler.KeyDown(Keys.Up))
            {
                motion.Y = -this.Speed;
            }
            else if (InputHandler.KeyDown(Keys.Down))
            {
                motion.Y = this.Speed;
            }

            if (motion != Vector2.Zero)
            {
                motion.Normalize();
                position += motion * speed;
                this.LockCamera();
            }
        }

        private void LockCamera()
        {
            this.position.X = MathHelper.Clamp(
                this.position.X,
                0,
                TileMap.WidthInPixels - this.ViewportRectangle.Width);

            this.position.Y = MathHelper.Clamp(
                this.position.Y,
                0,
                TileMap.HeightInPixels - this.ViewportRectangle.Height);
        }

        public void LockToSprite(AnimatedSprite sprite)
        {
            this.position.X = sprite.Position.X + sprite.Width / 2 - (this.ViewportRectangle.Width / 2);
            this.position.Y = sprite.Position.Y + sprite.Height / 2 - (this.ViewportRectangle.Height / 2);
            this.LockCamera();
        }

        public void ToggleCameraMode()
        {
            if (this.mode == CameraMode.Follow)
            {
                this.mode = CameraMode.Free;
            }
            else if (this.mode == CameraMode.Free)
            {
                this.mode = CameraMode.Follow;
            }
        }
    }
}
